package com.safety51.bootstrap.demo;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * Created by liuyuancheng on 2022/6/14  <br/>
 *
 * @author liuyuancheng
 */
@Slf4j
public class AESUtils {

    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";

    /**
     * SecretKeySpec类是KeySpec接口的实现类,用于构建秘密密钥规范
     */
    private String key;

    public AESUtils() {
        nextKey();
    }

    public AESUtils(byte[] bytes) {
        key = Base64.getEncoder().encodeToString(bytes);
    }

    public AESUtils(String base64) {
        key = base64;
    }

    public void nextKey() {
        // 加密时使用的随机密码
        KeyGenerator kg = null;
        try {
            kg = KeyGenerator.getInstance("AES");
            kg.init(128);
            SecretKey desedeKey = kg.generateKey();
            key = org.apache.commons.codec.binary.Base64.encodeBase64String(desedeKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public byte[] getKey() {
        return Base64.getDecoder().decode(this.key);
    }

    public String getKeyBase64() {
        return key;
    }

    private static SecretKeySpec getKey(String strKey) {
        byte[] arrBTmp = new byte[0];
        arrBTmp = strKey.getBytes(StandardCharsets.UTF_8);
        byte[] arrB = new byte[32]; // 创建一个空的32位字节数组（默认值为0）
        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }
        SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES");
        return skeySpec;
    }

    /**
     * AES加密
     *
     * @param content json
     * @return
     * @throws Exception
     */
    public String encryptData(String content) {

        try {
            log.debug("AES加密原文={}", content);
            String csn = Charset.defaultCharset().name();
            log.debug("defaultCharset={}", csn);
            SecretKeySpec skeySpec = getKey(this.key);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = new byte[0];
            encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return org.apache.commons.codec.binary.Base64.encodeBase64String(encrypted);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * AES解密
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
//    public String decryptData(String base64Data) {
//        Cipher cipher = null;
//        try {
//            cipher = Cipher.getInstance(ALGORITHM_STR);
//            cipher.init(Cipher.DECRYPT_MODE, key);
//            return new String(cipher.doFinal(new BASE64Decoder().decodeBuffer(base64Data)));
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (NoSuchPaddingException e) {
//            e.printStackTrace();
//        } catch (IllegalBlockSizeException e) {
//            e.printStackTrace();
//        } catch (BadPaddingException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (InvalidKeyException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    /**
     * hex字符串 转 byte数组
     *
     * @param s
     * @return
     */
    private static byte[] hex2byte(String s) {
        if (s.length() % 2 == 0) {
            return hex2byte(s.getBytes(), 0, s.length() >> 1);
        } else {
            return hex2byte("0" + s);
        }
    }

    private static byte[] hex2byte(byte[] b, int offset, int len) {
        byte[] d = new byte[len];
        for (int i = 0; i < len * 2; i++) {
            int shift = i % 2 == 1 ? 0 : 4;
            d[i >> 1] |= Character.digit((char) b[offset + i], 16) << shift;
        }
        return d;
    }

    public static void main(String[] args) throws Exception {
        AESUtils util = new AESUtils("abcdefghijklmnop".getBytes(StandardCharsets.UTF_8)); // 密钥
        System.out.println("cardNo:" + util.encryptData("1234")); // 加密
//        System.out.println("exp:" + util.decryptData("34+Jzs4KkwaCQWVyyAgwLA==")); // 解密
    }

}
